using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
using System.Windows.Controls;
using Microsoft.Practices.CompositeUI;
using Microsoft.Practices.CompositeUI.SmartParts;
using Microsoft.Practices.ObjectBuilder;

namespace SCSFContrib.CompositeUI.WPF.Workspaces
{
	/// <summary>
	/// A base class for all <see cref="ContentControl"/>-based workspaces.
	/// </summary>
	/// <remarks>
	/// <para>
	/// For any workspace implementation that inherits from <see cref="ContentControl"/>, this base class saves the trouble of implementing the
	/// <see cref="IComposableWorkspace{TSmartPart, TSmartPartInfo}"/> interface. Subclasses need only provide implementations for
	/// <see cref="OnShow"/>, <see cref="OnActivate"/>, <see cref="OnHide"/>, <see cref="OnClose"/> and optionally
	/// <see cref="OnApplySmartPartInfo"/>.
	/// </para>
	/// </remarks>
	/// <typeparam name="TSmartPart">
	/// The type of smart parts supported by the workspace.
	/// </typeparam>
	/// <typeparam name="TSmartPartInfo">
	/// The type of the smart part information received by the workspace.
	/// </typeparam>
	public abstract class ContentControlWorkspace<TSmartPart, TSmartPartInfo> : ContentControl, IComposableWorkspace<TSmartPart, TSmartPartInfo>
		where TSmartPartInfo : ISmartPartInfo, new()
	{
		private readonly WorkspaceComposer<TSmartPart, TSmartPartInfo> _composer;

		/// <summary>
		/// Gets the active smart part in this workspace, or <see langword="null"/> if no smart part is active.
		/// </summary>
		public object ActiveSmartPart
		{
			get
			{
				return _composer.ActiveSmartPart;
			}
		}

		/// <summary>
		/// Gets a snapshot of the current smart parts contained in this workspace.
		/// </summary>
		public ReadOnlyCollection<object> SmartParts
		{
			get
			{
				return _composer.SmartParts;
			}
		}

		/// <summary>
		/// Gets the collection of smart parts being managed by this workspace.
		/// </summary>
		protected IList<TSmartPart> InnerSmartParts
		{
			get
			{
				return _composer.InnerSmartParts;
			}
		}

		/// <summary>
		/// Gets the <see cref="WorkspaceComposer{TSmartPart, TSmartPartInfo}"/> for this <c>ContentControlWorkspace</c>.
		/// </summary>
		protected Microsoft.Practices.CompositeUI.SmartParts.WorkspaceComposer<TSmartPart, TSmartPartInfo> Composer
		{
			get
			{
				return _composer;
			}
		}

		/// <summary>
		/// Occurs whenever a smart part is activated by this workspace.
		/// </summary>
		public event EventHandler<WorkspaceEventArgs> SmartPartActivated;

		/// <summary>
		/// Occurs whenever a smart part is about to be closed by this workspace.
		/// </summary>
		public event EventHandler<WorkspaceCancelEventArgs> SmartPartClosing;

		/// <summary>
		/// Constructs an instance of <c>ContentControlWorkspace</c>.
		/// </summary>
		protected ContentControlWorkspace()
		{
			_composer = new WorkspaceComposer<TSmartPart, TSmartPartInfo>(this);
		}

		/// <summary>
		/// Provides dependencies to this <c>ContentControlWorkspace</c>.
		/// </summary>
		/// <param name="workItem">
		/// The <see cref="WorkItem"/>.
		/// </param>
		[InjectionMethod]
		public void InjectDependencies(WorkItem workItem)
		{
			_composer.WorkItem = workItem;
		}

		/// <summary>
		/// Activates the specified smart part in this workspace.
		/// </summary>
		/// <param name="smartPart">
		/// The smart part to activate.
		/// </param>
		public void Activate(object smartPart)
		{
			_composer.Activate(smartPart);
		}

		/// <summary>
		/// Applies the specified smart part info to the smart part in this workspace.
		/// </summary>
		/// <param name="smartPart">
		/// The smart part to which <paramref name="smartPartInfo"/> will be applied.
		/// </param>
		/// <param name="smartPartInfo">
		/// The <typeparamref name="TSmartPartInfo"/> instance to apply to <paramref name="smartPart"/>.
		/// </param>
		public void ApplySmartPartInfo(object smartPart, ISmartPartInfo smartPartInfo)
		{
			_composer.ApplySmartPartInfo(smartPart, smartPartInfo);
		}

		/// <summary>
		/// Closes the specified smart part.
		/// </summary>
		/// <param name="smartPart">
		/// The smart part in this workspace that should be closed.
		/// </param>
		public void Close(object smartPart)
		{
			_composer.Close(smartPart);
		}

		/// <summary>
		/// Hides the specified smart part.
		/// </summary>
		/// <param name="smartPart">
		/// The smart part in this workspace to be hidden.
		/// </param>
		public void Hide(object smartPart)
		{
			_composer.Hide(smartPart);
		}

		/// <summary>
		/// Shows the specified smart part.
		/// </summary>
		/// <param name="smartPart">
		/// The smart part to show.
		/// </param>
		public void Show(object smartPart)
		{
			_composer.Show(smartPart);
		}

		/// <summary>
		/// Shows the specified smart part.
		/// </summary>
		/// <param name="smartPart">
		/// The smart part to show.
		/// </param>
		/// <param name="smartPartInfo">
		/// The instance of <typeparamref name="TSmartPartInfo"/> that provides any extraneous information to be used in the displaying of
		/// <paramref name="smartPart"/>.
		/// </param>
		public void Show(object smartPart, ISmartPartInfo smartPartInfo)
		{
			_composer.Show(smartPart, smartPartInfo);
		}

		/// <summary>
		/// Converts from <paramref name="source"/> to <typeparamref name="TSmartPartInfo"/>.
		/// </summary>
		/// <param name="source">
		/// The <see cref="ISmartPartInfo"/> instance to convert.
		/// </param>
		/// <returns>
		/// An instance of type <typeparamref name="TSmartPartInfo"/>.
		/// </returns>
		TSmartPartInfo IComposableWorkspace<TSmartPart, TSmartPartInfo>.ConvertFrom(ISmartPartInfo source)
		{
			return OnConvertFrom(source);
		}

		/// <summary>
		/// Raises the <see cref="SmartPartActivated"/> event.
		/// </summary>
		/// <param name="e">
		/// Event arguments.
		/// </param>
		void IComposableWorkspace<TSmartPart, TSmartPartInfo>.RaiseSmartPartActivated(WorkspaceEventArgs e)
		{
			OnSmartPartActivated(e);
		}

		/// <summary>
		/// Raises the <see cref="SmartPartClosing"/> event.
		/// </summary>
		/// <param name="e">
		/// Event arguments.
		/// </param>
		void IComposableWorkspace<TSmartPart, TSmartPartInfo>.RaiseSmartPartClosing(WorkspaceCancelEventArgs e)
		{
			OnSmartPartClosing(e);
		}

		/// <summary>
		/// Applies the specified smart part info to the smart part in this workspace.
		/// </summary>
		/// <param name="smartPart">
		/// The smart part to which <paramref name="smartPartInfo"/> will be applied.
		/// </param>
		/// <param name="smartPartInfo">
		/// The <typeparamref name="TSmartPartInfo"/> instance to apply to <paramref name="smartPart"/>.
		/// </param>
		public virtual void OnApplySmartPartInfo(TSmartPart smartPart, TSmartPartInfo smartPartInfo)
		{
			//does nothing by default
		}

		/// <summary>
		/// Shows the specified smart part.
		/// </summary>
		/// <param name="smartPart">
		/// The smart part to show.
		/// </param>
		/// <param name="smartPartInfo">
		/// The instance of <typeparamref name="TSmartPartInfo"/> that provides any extraneous information to be used in the displaying of
		/// <paramref name="smartPart"/>.
		/// </param>
		public abstract void OnShow(TSmartPart smartPart, TSmartPartInfo smartPartInfo);

		/// <summary>
		/// Activates the specified smart part in this workspace.
		/// </summary>
		/// <param name="smartPart">
		/// The smart part to activate.
		/// </param>
		public abstract void OnActivate(TSmartPart smartPart);

		/// <summary>
		/// Hides the specified smart part.
		/// </summary>
		/// <param name="smartPart">
		/// The smart part in this workspace to be hidden.
		/// </param>
		public abstract void OnHide(TSmartPart smartPart);

		/// <summary>
		/// Closes the specified smart part.
		/// </summary>
		/// <param name="smartPart">
		/// The smart part in this workspace that should be closed.
		/// </param>
		public abstract void OnClose(TSmartPart smartPart);

		/// <summary>
		/// Raises the <see cref="SmartPartActivated"/> event.
		/// </summary>
		/// <param name="e">
		/// Event arguments.
		/// </param>
		protected virtual void OnSmartPartActivated(WorkspaceEventArgs e)
		{
			EventHandler<WorkspaceEventArgs> handler = SmartPartActivated;

			if (handler != null)
			{
				handler(this, e);
			}
		}

		/// <summary>
		/// Raises the <see cref="SmartPartClosing"/> event.
		/// </summary>
		/// <param name="e">
		/// Event arguments.
		/// </param>
		protected virtual void OnSmartPartClosing(WorkspaceCancelEventArgs e)
		{
			EventHandler<WorkspaceCancelEventArgs> handler = SmartPartClosing;

			if (handler != null)
			{
				handler(this, e);
			}
		}

		/// <summary>
		/// Converts <paramref name="source"/> into an instance of <typeparamref name="TSmartPartInfo"/>.
		/// </summary>
		/// <param name="source">
		/// The instance of <see cref="ISmartPartInfo"/> to be converted.
		/// </param>
		/// <returns>
		/// <paramref name="source"/> converted to an instance of <typeparamref name="TSmartPartInfo"/>.
		/// </returns>
		protected virtual TSmartPartInfo OnConvertFrom(ISmartPartInfo source)
		{
			return SmartPartInfo.ConvertTo<TSmartPartInfo>(source);
		}
	}
}
